package org.bedracket.pgeg.datagen.loot;

import net.minecraft.advancements.critereon.StatePropertiesPredicate;
import net.minecraft.data.loot.BlockLootSubProvider;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraftforge.registries.RegistryObject;
import org.bedracket.pgeg.block.TomatoCrop;
import org.bedracket.pgeg.init.ModBlocks;
import org.bedracket.pgeg.init.ModItems;

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ModBlockLoot extends BlockLootSubProvider {

    private static final Set<Item> EXPLOSION_RESISTANT =
            Stream.of(Blocks.DRAGON_EGG, Blocks.BEACON, Blocks.CONDUIT,
                    Blocks.SKELETON_SKULL, Blocks.WITHER_SKELETON_SKULL,
                    Blocks.PLAYER_HEAD, Blocks.ZOMBIE_HEAD, Blocks.CREEPER_HEAD,
                    Blocks.DRAGON_HEAD, Blocks.PIGLIN_HEAD, Blocks.SHULKER_BOX,
                    Blocks.BLACK_SHULKER_BOX, Blocks.BLUE_SHULKER_BOX, Blocks.BROWN_SHULKER_BOX,
                    Blocks.CYAN_SHULKER_BOX, Blocks.GRAY_SHULKER_BOX, Blocks.GREEN_SHULKER_BOX,
                    Blocks.LIGHT_BLUE_SHULKER_BOX, Blocks.LIGHT_GRAY_SHULKER_BOX, Blocks.LIME_SHULKER_BOX,
                    Blocks.MAGENTA_SHULKER_BOX, Blocks.ORANGE_SHULKER_BOX, Blocks.PINK_SHULKER_BOX,
                    Blocks.PURPLE_SHULKER_BOX, Blocks.RED_SHULKER_BOX, Blocks.WHITE_SHULKER_BOX,
                    Blocks.YELLOW_SHULKER_BOX).map(ItemLike::asItem).collect(Collectors.toSet());

    protected ModBlockLoot() {
        super(EXPLOSION_RESISTANT, FeatureFlags.REGISTRY.allFlags());
    }

    @Override
    protected void generate() {
        cropDrop(ModBlocks.TOMATO.get(), TomatoCrop.AGE, 7,
                ModItems.TOMATO.get(), ModItems.TOMATO.get());
        oreDrop(ModBlocks.AIR_INFUSED_STONE.get(), ModItems.AIR_SHARD.get());
        oreDrop(ModBlocks.AQUA_INFUSED_STONE.get(), ModItems.AQUA_SHARD.get());
        oreDrop(ModBlocks.EARTH_INFUSED_STONE.get(), ModItems.EARTH_SHARD.get());
        oreDrop(ModBlocks.ENTROPY_INFUSED_STONE.get(), ModItems.ENTROPY_SHARD.get());
        oreDrop(ModBlocks.FIRE_INFUSED_STONE.get(), ModItems.FIRE_SHARD.get());
        oreDrop(ModBlocks.ORDER_INFUSED_STONE.get(), ModItems.ORDER_SHARD.get());
        oreDrop(ModBlocks.AIR_INFUSED_DEEPSLATE.get(), ModItems.AIR_SHARD.get());
        oreDrop(ModBlocks.AQUA_INFUSED_DEEPSLATE.get(), ModItems.AQUA_SHARD.get());
        oreDrop(ModBlocks.EARTH_INFUSED_DEEPSLATE.get(), ModItems.EARTH_SHARD.get());
        oreDrop(ModBlocks.ENTROPY_INFUSED_DEEPSLATE.get(), ModItems.ENTROPY_SHARD.get());
        oreDrop(ModBlocks.FIRE_INFUSED_DEEPSLATE.get(), ModItems.FIRE_SHARD.get());
        oreDrop(ModBlocks.ORDER_INFUSED_DEEPSLATE.get(), ModItems.ORDER_SHARD.get());
        dropSelf(ModBlocks.BRIMSTONE_ORE.get());
        dropSelf(ModBlocks.METEORITE_ORE.get());
        dropSelf(ModBlocks.MITHRIL_ORE.get());
        dropSelf(ModBlocks.ORICHALCUM_ORE.get());
        dropSelf(ModBlocks.SATURNIUM_ORE.get());
        dropSelf(ModBlocks.SILVER_ORE.get());
        dropSelf(ModBlocks.DEEPSLATE_BRIMSTONE_ORE.get());
        dropSelf(ModBlocks.DEEPSLATE_METEORITE_ORE.get());
        dropSelf(ModBlocks.DEEPSLATE_MITHRIL_ORE.get());
        dropSelf(ModBlocks.DEEPSLATE_ORICHALCUM_ORE.get());
        dropSelf(ModBlocks.DEEPSLATE_SATURNIUM_ORE.get());
        dropSelf(ModBlocks.DEEPSLATE_SILVER_ORE.get());
    }

    private void cropDrop(Block block, IntegerProperty age, int matureValue, ItemLike result, ItemLike seed) {
        LootItemCondition.Builder loot$builder =
                LootItemBlockStatePropertyCondition.hasBlockStateProperties(block)
                        .setProperties(StatePropertiesPredicate.Builder.properties()
                                .hasProperty(age, matureValue));
        this.add(block, createCropDrops(block, result.asItem(), seed.asItem(), loot$builder));
    }

    private void oreDrop(Block block, Item drop) {
        add(block, (ore) -> createOreDrop(ore, drop));
    }

    @Override
    protected Iterable<Block> getKnownBlocks() {
        return ModBlocks.BLOCKS.getEntries().stream().map(RegistryObject::get).toList();
    }
}
